const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

const DllReferencePlugin = require("webpack/lib/DllReferencePlugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
// const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const path = require("path");
const WebpackBar = require("webpackbar");

const smp = new SpeedMeasurePlugin();

const isProduction = process.env.NODE_ENV === "production";

// const WorkboxWebpackPlugin = require("workbox-webpack-plugin");
const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
const paths = require("./paths");
const options = {
  fileName: "asset-manifest.json",
  publicPath: paths.publicUrlOrPath,
  generate: (seed, files, entrypoints) => {
    const manifestFiles = files.reduce((manifest, file) => {
      manifest[file.name] = file.path;
      return manifest;
    }, seed);
    const entrypointFiles = entrypoints.app.filter(
      (fileName) => !fileName.endsWith(".map")
    );

    return {
      files: manifestFiles,
      entrypoints: entrypointFiles,
    };
  },
};

module.exports = smp.wrap({
  // mode: "production",
  mode: "development",
  devtool: "source-map",
  devServer: {
    port: 3000,
    historyApiFallback: true,
    client: {
      overlay: false,
    },
  },
  context: __dirname,
  entry: {
    app: "./src/main.tsx",
    // add: './src/hashtest/add.js',
    // sub: './src/hashtest/sub.js',
    // test: './src/test.js' // 测试函数lazy parsing, eager parsing
  },
  performance: {
    hints: "warning",
    maxAssetSize: 3000000,
    maxEntrypointSize: 5000000,
  },
  output: {
    path: `${__dirname}/dist`,
    filename: "[name].[contenthash].bundle.js", // contenthash
    chunkFilename: "[name].[contenthash:8].bundle.js", // 按需用的文件
  },
  optimization: {
    minimizer: [
      // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
      // `...`,
      new CssMinimizerPlugin(),
    ],
    splitChunks: {
      cacheGroups: {
        chunks: 'all',
        vendor: {
          name: "vendor",
          test: /[\\/]node_modules[\\/]/,
          minSize: 0, // 全部
          minChunks: 1, // 最新多少个 chunk
          priority: 10, // 高优
          chunks: "initial", // initial 同步
        },
        common: {
          name: "common",
          test: /[\\/]src[\\/]/,
          chunks: "all",
          minSize: 0,
          minChunks: 2,
        },
      },
    },
  },
  resolve: {
    extensions: [ '.tsx', '.ts', '.js','.jsx' ], // 优化打包速度
    // 使用绝对路径指明第三方模块存放的位置，以减少搜索步骤
    // 其中 __dirname 表示当前工作目录，也就是项目根目录
    // modules: [path.resolve(__dirname, 'node_modules')], // 优化打包速度
    // alias: {
    //   'react': path.resolve(
    //     __dirname,
    //     '../node_modules/react/umd/react.production.min.js' // 性能优化
    //   ),
    // }
  },

  plugins: [
    new webpack.DefinePlugin({
      "process.env.PUBLIC_URL": JSON.stringify(""),
    }),
    new HtmlWebpackPlugin({
      template: "index.html",
    }),
    new CopyPlugin({
      patterns: [{ from: "./img/*" }],
    }),
    new MiniCssExtractPlugin({
      filename: "[name].[contenthash].css",
      chunkFilename: "[id].[contenthash:8].css",
    }),
    /* 动态链接库引用 */
    // new DllReferencePlugin({
    //   manifest: require(`${__dirname}/dll/react.manifest.json`),
    // }),

    // new WorkboxWebpackPlugin.GenerateSW({
    //   clientsClaim: true,
    //   skipWaiting: true,
    //   exclude: [/\.map$/, /asset-manifest\.json$/],
    //   navigateFallback: paths.publicUrlOrPath + "index.html",
    //   navigateFallbackDenylist: [
    //     // Exclude URLs starting with /_, as they're likely an API call
    //     new RegExp("^/_"),
    //     // Exclude any URLs whose last part seems to be a file extension
    //     // as they're likely a resource and not a SPA route.
    //     // URLs containing a "?" character won't be blacklisted as they're likely
    //     // a route with query params (e.g. auth callbacks).
    //     new RegExp("/[^/?]+\\.[^/]+$"),
    //   ],
    // }),

    new WebpackManifestPlugin(options),
    new MiniCssExtractPlugin(),
    new CleanWebpackPlugin(),
    // new BundleAnalyzerPlugin(),
    new WebpackBar(),
    new webpack.IgnorePlugin({
      // 优化size
      resourceRegExp: /^\.\/locale$/, // 忽略content设置的库中的某个文件夹
      contextRegExp: /moment$/, // 要被忽略某部分内容的库
    }),
    // new HardSourceWebpackPlugin(),
  ],

  module: {
    // noParse: /lodash|jQuery|react\.production\.min\.js$/,// 优化打包速度
    rules: [
      {
        test:  /\.ts(x?)$/,
        use: [{ loader: 'babel-loader' }, { loader: 'ts-loader' }],
        exclude: /node_modules/,
      },
      {
        test: /.s?css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
      { test: /\.ts$/, use: "ts-loader" },
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: "babel-loader",
          options: {
            cacheDirectory: true, // 缓存转换出的结果，// 优化打包速度
            // include: path.resolve(__dirname, '../src'),
            presets: ["@babel/preset-env"],
          },
        },
      },
      {
        test: /\.(png|jpg|gif)$/i,
        dependency: { not: ["url"] },
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 8192,
            },
          },
        ],
      },
    ],
  },
  //   module: {
  //     noParse: /lodash/,
  //     rules: [
  //       {
  //         test: /\.jsx?$/,
  //         loader: "babel-loader",
  //         include: /src/,
  //         exclude: /node_modules/,
  //         query: {
  //           presets: ["@babel/preset-react"],
  //         },
  //       },
  //   {
  //     test: /(\.css$)/,
  //     use: [
  //       isProduction
  //         ? {
  //             loader: MiniCssExtractPlugin.loader,
  //           }
  //         : {
  //             loader: "style-loader",
  //           },
  //       {
  //         loader: "css-loader",
  //       },
  //       {
  //         loader: "postcss-loader",
  //       },
  //     ],
  //   },
  //   {
  //     test: /\.(png|woff|woff2|eot|ttf)$/,
  //     loader: "url-loader?limit=100000",
  //   },
  //   {
  //     test: /\.(png|jp(e*)g|gif)$/,
  //     use: [
  //       {
  //         loader: "file-loader",
  //         options: {
  //           name: "images/[hash]-[name].[ext]",
  //         },
  //       },
  //     ],
  //   },
  //   {
  //     test: /\.svg$/,
  //     use: ["@svgr/webpack"],
  //   },
  // ],
  //   },
});
